#pragma once
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <fstream>
#include <cassert>

#include "../common/common.hpp"
#include "../common/log.hpp"

namespace wjh_model
{
    using namespace wjh_util;

    const std::string QuestionListPath = "./Questions/Questions-list.txt";
    const std::string QuestionsPath = "./Questions/";
    struct Question
    {
        //1 两数之和 简单 1 50000
        std::string number; //题目编号
        std::string name; //题目名
        std::string star; //题目难易度
        int cpuLimit; //时间限制
        int memLimit; //内存限制
        std::string desc; //题目的描述
        std::string header; //题目预设值的代码
        std::string tail; //题目的测试用例
    };

    class Model
    {
    public:
        Model()
        {
            assert(LoadQuestionList(QuestionListPath));
        }

        //获取全部题目
        bool GetAllQuestions(std::vector<Question>& allQuestions)
        {
            if(_NumToQuestion.size() == 0) 
            {
                logMessage(ERROR, "%s %d %s", __FILE__, __LINE__, "加载题库失败，请检查题库");
                return false;
            }
            for(const auto& e : _NumToQuestion)
            {
                allQuestions.push_back(e.second);
            }

            logMessage(NORMAL, "%s", "加载题库成功");
            return true;
        }

        //获取单个题目
        bool GetOneQuestion(const std::string &number, Question& oneQuestion)
        {
            if(_NumToQuestion.size() == 0) 
            {
                logMessage(ERROR, "%s %d %s", __FILE__, __LINE__, "加载题目失败，请检查题库");
                return false;
            }
            auto it = _NumToQuestion.find(number);
            if(it == _NumToQuestion.end()) return false;

            oneQuestion = it->second;
            logMessage(NORMAL, "%s %s%s", "加载指定题目：", number.c_str(), " 成功");
            return true;
        }

        ~Model() = default;

    private:
        bool LoadQuestionList(const std::string& QuestionListPath)
        {
            std::ifstream is(QuestionListPath);
            if(!is.is_open()) 
            {
                logMessage(FATAL, "%s %d %s", __FILE__, __LINE__, "加载题库失败，请检查文件是否存在或者路径是否错误");
                return false;
            }
            
            std::string line;
            while (getline(is, line))
            {
                std::vector<std::string> target;
                StringUtil::SplitStr(line, target, " ");
                if(target.size() != 5)
                {
                    //不符合要求丢弃
                    logMessage(ERROR, "%s %d %s", __FILE__, __LINE__, "文件格式不对");
                    continue;
                }

                Question q;
                q.number = target[0];
                q.name = target[1];
                q.star = target[2];
                q.cpuLimit = atoi(target[3].c_str());
                q.memLimit = atoi(target[4].c_str());
                std::string AssignQuesPath = QuestionsPath + target[0] + "/";
                FileUtil::FileRead(AssignQuesPath + "description.txt", q.desc);
                FileUtil::FileRead(AssignQuesPath + "header.cpp", q.header);
                FileUtil::FileRead(AssignQuesPath + "tail.cpp", q.tail);

                _NumToQuestion.insert(std::make_pair(q.number, q));
            }

            is.close();
            return true;
        }

    private:
        std::unordered_map<std::string, Question> _NumToQuestion;
    };
}
